#include "types.h"
#include "semaphore.h"
#include "user.h"

#define TSTACKSIZE 4096
#define N 11

int binsem_id;

void* beginthread() {

  // sleep in reverse order, meaning first thread sleeps the
  // longest, second thread sleep the second longest etc.
  // this is to ensure that they arrive to the binary semaphore
  // in the following order: N (N-1) ... 3 2 1.
  if ((thread_getid() - 1) == ((N/2)+1)) {
  	sleep(1000);
  } else {
  	sleep(((N+3 - (thread_getid() - 1)) + 1) * 20);
  }

  printf(1, "thread %d going to sleep on semaphore.\n", thread_getid());
  binary_sem_down(binsem_id);
  printf(1, "thread %d released from semaphore.\n", thread_getid());

  thread_exit((void*)0);
  return (void*)0;
}

int
main(int argc, char *argv[])
{
  void* ret_val;
  int tids[N]; // array of thread ids
  int i;
  
  binsem_id = binary_sem_create();
  binary_sem_down(binsem_id); // "lock" the semaphore
  
  for (i = 0; i < N; i++) {
  	tids[i] = thread_create(beginthread, malloc(TSTACKSIZE), TSTACKSIZE);
  }
  
  printf(1, "finished creating threads...\n");
  sleep( ((N+1) * N / 2) * 20 + 100 + 1200);
  printf(1, "about to wakeup threads...\n");
  
  for (i = 0; i < N; i++) {
  	binary_sem_up(binsem_id);
  	sleep(25);
  }
  
  for (i = 0; i < N; i++) {
  	thread_join(tids[i], &ret_val);
  }
  
//  binary_sem_destroy(binsem_id);

  exit();
}
